package com.onesports.intelligent.k12.polarlight.service.operation;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.onesports.framework.kit.common.util.ParamUtils;
import com.onesports.intelligent.k12.polarlight.common.domain.entity.BaseEntity;
import com.onesports.intelligent.k12.polarlight.common.errors.exceptions.BusinessException;
import com.onesports.intelligent.k12.polarlight.constant.CacheConstants;
import com.onesports.intelligent.k12.polarlight.domain.dto.common.EditStatusDTO;
import com.onesports.intelligent.k12.polarlight.domain.dto.common.ResetAccountPwdDTO;
import com.onesports.intelligent.k12.polarlight.domain.dto.operation.InsertOrganizationDTO;
import com.onesports.intelligent.k12.polarlight.domain.dto.operation.PageOrganizationDTO;
import com.onesports.intelligent.k12.polarlight.domain.dto.operation.UpdOrganizationDTO;
import com.onesports.intelligent.k12.polarlight.domain.dto.organization.OrgDisabledDTO;
import com.onesports.intelligent.k12.polarlight.domain.dto.organization.OrganizationStaffDTO;
import com.onesports.intelligent.k12.polarlight.domain.entity.market.Product;
import com.onesports.intelligent.k12.polarlight.domain.entity.organization.Organization;
import com.onesports.intelligent.k12.polarlight.domain.entity.organization.OrganizationCampus;
import com.onesports.intelligent.k12.polarlight.domain.entity.organization.OrganizationStaff;
import com.onesports.intelligent.k12.polarlight.domain.entity.sys.Account;
import com.onesports.intelligent.k12.polarlight.domain.vo.common.CanChoiceDataVO;
import com.onesports.intelligent.k12.polarlight.domain.vo.operation.PageOrganizationVO;
import com.onesports.intelligent.k12.polarlight.mapper.market.ProductMapper;
import com.onesports.intelligent.k12.polarlight.mapper.organization.OrganizationCampusMapper;
import com.onesports.intelligent.k12.polarlight.mapper.organization.OrganizationMapper;
import com.onesports.intelligent.k12.polarlight.mapper.organization.OrganizationStaffMapper;
import com.onesports.intelligent.k12.polarlight.mapper.sys.AccountMapper;
import com.onesports.intelligent.k12.polarlight.service.organization.OrganizationStaffService;
import com.onesports.intelligent.k12.polarlight.service.sys.AccountService;
import com.onesports.intelligent.k12.polarlight.service.sys.ProductService;
import com.onesports.intelligent.k12.polarlight.util.BeanCopyUtil;
import com.onesports.intelligent.k12.polarlight.util.NoUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * @author Wsy
 **/
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = CacheConstants.ORGANIZATION)
public class OrganizationService extends ServiceImpl<OrganizationMapper, Organization> {

    private final OrganizationMapper mapper;
    private final OrganizationCampusMapper organizationCampusMapper;
    private final AccountService accountService;
    private final OrganizationStaffService organizationStaffService;
    private final ProductService productService;
    private final ProductMapper productMapper;

    public static final String ID_KEY_PREFIX = "'id:'";

    /**
     * 运营团队校区联动下拉
     *
     * @param teamName 团队名称
     * @return List<CanChoiceDataVO>
     */
    public List<CanChoiceDataVO> dropDown(String teamName, String provinceCode, String cityCode, String areaCode) {
        //获取所有运营团队(机构)
        List<Organization> list = this.list(new LambdaQueryWrapper<Organization>()
                .like(ParamUtils.isNotEmpty(teamName), Organization::getOrganizationName, teamName)
                .eq(ParamUtils.isNotEmpty(provinceCode), Organization::getProvince, provinceCode)
                .eq(ParamUtils.isNotEmpty(cityCode), Organization::getCity, cityCode)
                .eq(ParamUtils.isNotEmpty(areaCode), Organization::getArea, areaCode)
        );
        if (ParamUtils.isEmpty(list)) {
            return new ArrayList<>();
        }

        List<String> organizationIds = list.stream().map(BaseEntity::getId).collect(Collectors.toList());
        //根据运营团队id获取所有校区
        List<OrganizationCampus> organizationCampuses = this.organizationCampusMapper.selectList(new LambdaQueryWrapper<OrganizationCampus>()
                .in(OrganizationCampus::getOrganizationId, organizationIds));
        //封装返回数据
        Map<String, List<OrganizationCampus>> organizationCampusMap = null;
        if (ParamUtils.isNotEmpty(organizationCampuses)) {
            organizationCampusMap = organizationCampuses.stream().collect(Collectors.groupingBy(OrganizationCampus::getOrganizationId));
        }

        Map<String, List<OrganizationCampus>> finalOrganizationCampusMap = organizationCampusMap;
        return list.stream().map(i -> {
            List<CanChoiceDataVO> child = new ArrayList<>();
            if (ParamUtils.isNotEmpty(finalOrganizationCampusMap)) {
                List<OrganizationCampus> campuses = finalOrganizationCampusMap.get(i.getId());
                if (ParamUtils.isNotEmpty(campuses)) {
                    child = campuses.stream().map(c -> CanChoiceDataVO.builder().id(c.getId()).name(c.getCampusName()).build()).collect(Collectors.toList());
                }
            }
            return CanChoiceDataVO.builder().id(i.getId()).name(i.getOrganizationName()).data(child).build();
        }).collect(Collectors.toList());
    }


    /**
     * 新增运营团队（组织）
     *
     * @param dto 入参
     */
    @Transactional(rollbackFor = Exception.class)
    public void add(InsertOrganizationDTO dto) {
        // 查看名称是否重复
        checkPhone(null, dto.getOrganizationName());
        Organization entity = new Organization();
        BeanCopyUtil.copyProperties(dto, entity);
        entity.setOrganizationCode(NoUtil.code());
        this.mapper.insert(entity);
        // 添加运营团队负责人
        organizationStaffService.addSuper(dto.getPrincipal(), dto.getPhoneNumber(), entity.getId());
    }


    /**
     * function: 修改运营团队
     *
     * @param dto 更新运营团队入参
     * @author WangCX
     * @since 2022/7/11 14:46
     */
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(key = ID_KEY_PREFIX + "+#dto.id")
    public void upd(UpdOrganizationDTO dto) {
        // 查看名称是否重复
        checkPhone(dto.getId(), dto.getOrganizationName());
        Organization organization = this.getById(dto.getId());
        if (!organization.getPrincipal().equals(dto.getPrincipal()) ||
                !dto.getPhoneNumber().equals(organization.getPhoneNumber())) {
            OrganizationStaffDTO staffDTO = new OrganizationStaffDTO();
            BeanCopyUtil.copyProperties(dto, staffDTO);
            staffDTO.setPhone(dto.getPhoneNumber());
            staffDTO.setStaffName(dto.getPrincipal());
            staffDTO.setOrganizationId(dto.getId());
            staffDTO.setId(getStaffIdByOrgId(dto.getId()));
            this.organizationStaffService.edit(staffDTO, false);
        }
        Organization entity = new Organization();
        BeanCopyUtil.copyProperties(dto, entity);
        this.mapper.updateById(entity);
    }


    /**
     * function：根据运营团队Id获取当前负责人Id
     *
     * @param orgId 运营团队Id
     * @return staffId 运营团队负责人Id
     * @author wangcx
     * @since 2022/8/1 10:28
     */
    public String getStaffIdByOrgId(String orgId) {
        return organizationStaffService.getOne(new LambdaQueryWrapper<OrganizationStaff>()
                .eq(OrganizationStaff::getOrganizationId, orgId)
                .eq(OrganizationStaff::getIsPrincipal, true)).getId();
    }


    /**
     * 查看手机号是否重复
     *
     * @param id   主键id
     * @param name 运营团队名称
     */
    private void checkPhone(String id, String name) {
        Long aLong = this.mapper.selectCount(new LambdaQueryWrapper<Organization>()
                .eq(Organization::getOrganizationName, name)
                .ne(StringUtils.isNotEmpty(id), Organization::getId, id)
                .eq(Organization::getDeleted, false));
        if (aLong > 0) {
            throw new BusinessException("运营团队名称已存在！");
        }
    }

    /**
     * 重置负责人密码
     *
     * @param dto 入参
     */
    public void resetAccountPwd(ResetAccountPwdDTO dto) {
        accountService.resetPwdByPhone(dto.getPhone(), true);
    }

    /**
     * 分页查询组织列表
     *
     * @param page 页面
     * @param dto  入参
     * @return result 分页结果
     */
    public IPage<PageOrganizationVO> findPage(Page<PageOrganizationVO> page, PageOrganizationDTO dto) {
        IPage<PageOrganizationVO> result = this.mapper.findPage(page, dto);
        if (ParamUtils.isNotEmpty(result.getRecords())) {
            for (PageOrganizationVO record : result.getRecords()) {
                Long account = this.productMapper.selectCount(new LambdaQueryWrapper<Product>()
                        .eq(Product::getDeleted, false)
                        .eq(Product::getSell, true)
                        .eq(Product::getOrganizationId, record.getId()));
                record.setIsProduct(account > 0);
            }
        }

        return result;
    }

    /**
     * 删除：机构下没有校区以及没有排课表发布售卖才可删除
     *
     * @param id 团队id
     */
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(key = ID_KEY_PREFIX + "+#id")
    public void del(String id) {
        Long aLong = organizationCampusMapper.selectCount(new LambdaQueryWrapper<OrganizationCampus>()
                .eq(OrganizationCampus::getOrganizationId, id).eq(OrganizationCampus::getDeleted, false));
        if (aLong > 0) {
            throw new BusinessException("机构下存在校区,删除失败！");
        }

        organizationStaffService.delByOrganizationId(id);
        this.mapper.deleteById(id);

    }

    /**
     * 启用禁用：机构禁用，则机构以及所有下设的校区都无法登录使用
     *
     * @param dto 入参
     */
    @CacheEvict(key = ID_KEY_PREFIX + "+#dto.id")
    public void updStatus(EditStatusDTO dto) {
        List<String> orgIds = new ArrayList<>();
        orgIds.add(dto.getId());
        OrgDisabledDTO disabledDTO = new OrgDisabledDTO();
        disabledDTO.setStatus(dto.getStatus());
        disabledDTO.setOrganizationIds(orgIds);
        batchUpdateStatus(disabledDTO);
    }

    /**
     * 批量更新状态
     *
     * @param dto dto
     */
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(key = ID_KEY_PREFIX + "+#dto.organizationIds", cacheResolver = "customCacheResolver")
    public void batchUpdateStatus(OrgDisabledDTO dto) {
        //查询所有校区
        List<OrganizationCampus> organizationCampusList = organizationCampusMapper.selectList(null);
        //根据机构Id分组
        Map<String, List<OrganizationCampus>> ocMap = organizationCampusList.stream().collect(Collectors.groupingBy(OrganizationCampus::getOrganizationId));
        // 查询所有商品
        List<Product> productList = productService.list();
        //Map<String,List<Product>> productMap = null;
        //if(ParamUtils.isNotEmpty(productList)){
        //     productMap = productList.stream().collect(Collectors.groupingBy(Product::getOrganizationId));
        //}
        Map<String, List<Product>> productMap = productList.stream().collect(Collectors.groupingBy(Product::getOrganizationId));
        //根据机构Id查询机构
        List<Organization> organizationList = this.listByIds(dto.getOrganizationIds());
        for (Organization organization : organizationList) {
            if (Boolean.TRUE.equals(dto.getStatus())) {
                // 启用
                enableOrDisable(dto, ocMap, organization);
            } else {
                // 禁用
                enableOrDisable(dto, ocMap, organization);
                // 需要同步更改机构下商品状态
                if (ParamUtils.isNotEmpty(productMap)) {
                    List<Product> products = productMap.get(organization.getId());
                    if (ParamUtils.isNotEmpty(products)) {
                        products.forEach(e -> e.setSell(dto.getStatus()));
                        productService.updateBatchById(products);
                    }

                }
            }
        }
        this.updateBatchById(organizationList);

    }

    /**
     * 启用或禁用
     *
     * @param dto          dto
     * @param ocMap        机构校区
     * @param organization 机构
     */
    private void enableOrDisable(OrgDisabledDTO dto, Map<String, List<OrganizationCampus>> ocMap, Organization organization) {
        organization.setStatus(dto.getStatus());
        // 更新状态
        if (ParamUtils.isNotEmpty(ocMap)) {
            List<OrganizationCampus> ocList = ocMap.get(organization.getId());
            if (ParamUtils.isNotEmpty(ocList)) {
                ocList.forEach(e -> {
                    e.setStatus(dto.getStatus());
                    organizationCampusMapper.updateById(e);
                });
            }
        }

    }

    @Cacheable(key = ID_KEY_PREFIX + "+#id")
    public Organization getById(String id) {
        return super.getById(id);
    }

}

